package com.webull.information.center.carwler.common.util;

import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import com.webull.information.center.carwler.common.model.NetIpConfig;
import com.webull.information.center.carwler.dao.NetIpConfigDao;

@Component
public class CarwlerNetWorksUtil {
    protected final Logger logger = LogManager.getLogger(getClass());

    private @Autowired
    NetIpConfigDao netIpConfigDao;
    private Map<String, List<String>> collectionConfig = new ConcurrentHashMap<>();

    private @Value("${proxy_server:}")
    String wall_proxy_server;
    private ProxyService[] proxyService = null;

    /**
     * 留一个http专线代理用作S3翻墙
     */
    private @Value("${proxy_server_http:}")
    String wall_proxy_server_http;
    private ProxyService proxyServiceHttp = null;

    private @Value("${extend_proxy_server:}")
    String extend_proxy_server;
    private ProxyService[] extendProxyService = null;

    private @Value("${proxy_open:false}")
    boolean proxyOpen;

    private @Value("${outside_wall:false}")
    boolean outSideWall;

    /**
     * 获取翻墙代理（中-》美；美-》中）
     *
     * @return
     */
    public ProxyService getRandomWallProxyService() {
        if (proxyService == null || proxyService.length == 0)
            return null;
        int i = RandomUtils.nextInt(0, proxyService.length);
        return proxyService[i];
    }

    public ProxyService getWallProxyServiceHttp() {
        return proxyServiceHttp;
    }

    /**
     * 获取纯代理，用于隐藏服务ip.防止被封ip
     *
     * @return
     */
    private ProxyService getExtendProxyService() {
        if (extendProxyService == null || extendProxyService.length == 0)
            return null;
        int i = RandomUtils.nextInt(0, extendProxyService.length);
        return extendProxyService[i];
    }

    /**
     * 当前服务是否需要代理模式
     * 国内+ 翻墙 =true
     * 国内+不翻墙=false
     * 国外+ 不翻墙=true
     * 国外 +翻墙 =false
     *
     * @param original 是否需要翻墙
     * @return
     */
    public boolean isProxyOpen(boolean original) {
        return proxyOpen && (original ^ outSideWall);
    }

	public static void main(String[] args) {
		System.out.println(true ^ true);
	}
    /**
     * 翻墙代理和纯代理获取切换
     *
     * @param proxyOpen 是否要翻墙
     * @return
     */
    public ProxyService smartProxyModel(boolean proxyOpen) {
        if (proxyOpen) return getRandomWallProxyService();
        else return getExtendProxyService();
    }


    /**
     * 获取可用ip
     */
    public String getRefreshIp(String host, String... ignoreIps) {
        List<String> res = collectionConfig.get(host);
        if (res == null || res.isEmpty())
            return null;
        if (ignoreIps == null || ignoreIps.length == 0)
            return res.get(RandomUtils.nextInt(0, res.size()));
        else {
            for (int i = 0; i < res.size(); i++) {// 按顺序返回第一个符合的
                if (ArrayUtils.contains(ignoreIps, res.get(i)))
                    return res.get(i);
            }
        }
        return null;
    }

    @PostConstruct
    @Scheduled(cron = "0 */5 * * * ?")
    public void syncNetworksIP() {

        logger.info("syncNetworksIP sync start:" + toConfString());
        List<NetIpConfig> configs = netIpConfigDao.SearchAll();
        Map<String, List<String>> tmp = new ConcurrentHashMap<>();
        for (int i = 0; configs != null && i < configs.size(); i++) {
            NetIpConfig item = configs.get(i);
            String group = item.getHost();
            if (!tmp.containsKey(group)) {
                tmp.put(group, new ArrayList<String>());
            }
            if (!tmp.get(group).contains(item.getIp())) {
                tmp.get(group).add(item.getIp());
            }
        }
        collectionConfig = tmp;
        logger.info("syncNetworksIP sync result:" + toConfString());
        /**
         *
         */
        if (proxyService == null && !StringUtils.isBlank(wall_proxy_server)) {
            String[] split = StringUtils.split(wall_proxy_server, ",");
            ProxyService[] tmm = new ProxyService[split.length];
            for (int i = 0; i < split.length; i++) {
                ProxyService s5 = new ProxyService();
                s5.setAdress(StringUtils.substringBefore(split[i], ":"));
                s5.setPort(Integer.valueOf(StringUtils.substringAfter(split[i], ":")));
                tmm[i] = s5;
            }
            proxyService = tmm;
            logger.info("syncNetworksIP.wallProxyService sync result:" + ArrayUtils.toString(proxyService));
        }

        if (extendProxyService == null && !StringUtils.isBlank(extend_proxy_server)) {
            String[] split = StringUtils.split(extend_proxy_server, ",");
            ProxyService[] tmm = new ProxyService[split.length];
            for (int i = 0; i < split.length; i++) {
                ProxyService s5 = new ProxyService();
                s5.setAdress(StringUtils.substringBefore(split[i], ":"));
                s5.setPort(Integer.valueOf(StringUtils.substringAfter(split[i], ":")));
                tmm[i] = s5;
            }
            extendProxyService = tmm;
            logger.info("syncNetworksIP.extendProxyService sync result:" + ArrayUtils.toString(extendProxyService));
        }

        if (proxyServiceHttp == null && !StringUtils.isBlank(wall_proxy_server_http)) {
            ProxyService httpProxy = new ProxyService();
            httpProxy.setAdress(StringUtils.substringBefore(wall_proxy_server_http, ":"));
            httpProxy.setPort(Integer.valueOf(StringUtils.substringAfter(wall_proxy_server_http, ":")));
            proxyServiceHttp = httpProxy;
            logger.info("syncNetworksIP.proxyServiceHttp sync result:" + proxyServiceHttp);
        }

    }


    private String toConfString() {
        String s = "collectionConfig:{";
        for (Entry<String, List<String>> ent : collectionConfig.entrySet()) {
            s += ent.getKey() + ":" + ArrayUtils.toString(ent.getValue()) + ",";
        }
        s += "}";
        return s;
    }

    public static class ProxyService {
        private String adress;
        private Integer port;
        private InetSocketAddress inetSocketAddress = null;

        private ProxyService() {
        }

        private void setAdress(String adress) {
            this.adress = adress;
        }

        private void setPort(Integer port) {
            this.port = port;
        }

        public String getAdress() {
            return adress;
        }

        public Integer getPort() {
            return port;
        }

        public SocketAddress genSocketAddress() {
            if (inetSocketAddress == null && adress != null && port != null)
                inetSocketAddress = new InetSocketAddress(adress, port);
            return inetSocketAddress;
        }

        @Override
        public String toString() {
            return "Socks5Service{" + "adress='" + adress + '\'' + ", port=" + port + '}';
        }
    }

}
